#include "pec_crc.h"

#define TEST_PEC_CRC 0

static const uint16_t crcTable[] = {
    0x0000, 0x8B32, 0x9D56, 0x1664, 0xB19E, 0x3AAC, 0x2CC8, 0xA7FA, 0xE80E, 0x633C, 0x7558, 0xFE6A, 0x5990, 0xD2A2, 0xC4C6, 0x4FF4,
    0x5B2E, 0xD01C, 0xC678, 0x4D4A, 0xEAB0, 0x6182, 0x77E6, 0xFCD4, 0xB320, 0x3812, 0x2E76, 0xA544, 0x02BE, 0x898C, 0x9FE8, 0x14DA,
    0xB65C, 0x3D6E, 0x2B0A, 0xA038, 0x07C2, 0x8CF0, 0x9A94, 0x11A6, 0x5E52, 0xD560, 0xC304, 0x4836, 0xEFCC, 0x64FE, 0x729A, 0xF9A8,
    0xED72, 0x6640, 0x7024, 0xFB16, 0x5CEC, 0xD7DE, 0xC1BA, 0x4A88, 0x057C, 0x8E4E, 0x982A, 0x1318, 0xB4E2, 0x3FD0, 0x29B4, 0xA286,
    0xE78A, 0x6CB8, 0x7ADC, 0xF1EE, 0x5614, 0xDD26, 0xCB42, 0x4070, 0x0F84, 0x84B6, 0x92D2, 0x19E0, 0xBE1A, 0x3528, 0x234C, 0xA87E,
    0xBCA4, 0x3796, 0x21F2, 0xAAC0, 0x0D3A, 0x8608, 0x906C, 0x1B5E, 0x54AA, 0xDF98, 0xC9FC, 0x42CE, 0xE534, 0x6E06, 0x7862, 0xF350,
    0x51D6, 0xDAE4, 0xCC80, 0x47B2, 0xE048, 0x6B7A, 0x7D1E, 0xF62C, 0xB9D8, 0x32EA, 0x248E, 0xAFBC, 0x0846, 0x8374, 0x9510, 0x1E22,
    0x0AF8, 0x81CA, 0x97AE, 0x1C9C, 0xBB66, 0x3054, 0x2630, 0xAD02, 0xE2F6, 0x69C4, 0x7FA0, 0xF492, 0x5368, 0xD85A, 0xCE3E, 0x450C,
    0x4426, 0xCF14, 0xD970, 0x5242, 0xF5B8, 0x7E8A, 0x68EE, 0xE3DC, 0xAC28, 0x271A, 0x317E, 0xBA4C, 0x1DB6, 0x9684, 0x80E0, 0x0BD2,
    0x1F08, 0x943A, 0x825E, 0x096C, 0xAE96, 0x25A4, 0x33C0, 0xB8F2, 0xF706, 0x7C34, 0x6A50, 0xE162, 0x4698, 0xCDAA, 0xDBCE, 0x50FC,
    0xF27A, 0x7948, 0x6F2C, 0xE41E, 0x43E4, 0xC8D6, 0xDEB2, 0x5580, 0x1A74, 0x9146, 0x8722, 0x0C10, 0xABEA, 0x20D8, 0x36BC, 0xBD8E,
    0xA954, 0x2266, 0x3402, 0xBF30, 0x18CA, 0x93F8, 0x859C, 0x0EAE, 0x415A, 0xCA68, 0xDC0C, 0x573E, 0xF0C4, 0x7BF6, 0x6D92, 0xE6A0,
    0xA3AC, 0x289E, 0x3EFA, 0xB5C8, 0x1232, 0x9900, 0x8F64, 0x0456, 0x4BA2, 0xC090, 0xD6F4, 0x5DC6, 0xFA3C, 0x710E, 0x676A, 0xEC58,
    0xF882, 0x73B0, 0x65D4, 0xEEE6, 0x491C, 0xC22E, 0xD44A, 0x5F78, 0x108C, 0x9BBE, 0x8DDA, 0x06E8, 0xA112, 0x2A20, 0x3C44, 0xB776,
    0x15F0, 0x9EC2, 0x88A6, 0x0394, 0xA46E, 0x2F5C, 0x3938, 0xB20A, 0xFDFE, 0x76CC, 0x60A8, 0xEB9A, 0x4C60, 0xC752, 0xD136, 0x5A04,
    0x4EDE, 0xC5EC, 0xD388, 0x58BA, 0xFF40, 0x7472, 0x6216, 0xE924, 0xA6D0, 0x2DE2, 0x3B86, 0xB0B4, 0x174E, 0x9C7C, 0x8A18, 0x012A};

uint16_t pec_crc_init(void)
{
    return PEC_SAW_VEL;
}

uint16_t pec_crc_push(uint16_t crc, uint8_t data)
{
    return (crc << 8) ^ crcTable[((crc >> 8) ^ data) & 0xFF];
}

uint16_t pec_crc(uint8_t *data, int dataSizeBytes)
{
    uint16_t crc = PEC_SAW_VEL;
    for (int i = 0; i < dataSizeBytes; i++)
    {
        crc = (crc << 8) ^ crcTable[((crc >> 8) ^ data[i]) & 0xFF];
    }
    return crc;
}

#if TEST_PEC_CRC
#include "stdio.h"
int main(int args, char **argv)
{
    uint8_t datas[] = {
        0x01, 0x00, 0x3E, 0x10,
        0x01, 0x01, 0xB5, 0x22,
        0x02, 0x00, 0x2D, 0xF6,
        0x02, 0x01, 0xA6, 0xC4,
        0x02, 0x02, 0xB0, 0xA0,
        0x02, 0x03, 0x3B, 0x92,
        0x03, 0x00, 0xA5, 0xBA,
        0x03, 0x01, 0x2E, 0x88,
        0x04, 0x00, 0x0A, 0x3A,
        0x04, 0x01, 0x81, 0x08};
    uint8_t len = sizeof(datas) / sizeof(datas[0]) / 4;
    for (uint8_t i = 0; i < len; i++)
    {
        uint16_t crc, crc2;
        crc2 = pec_crc(&datas[i * 4], 2);
        crc = pec_crc_init();
        crc = pec_crc_push(crc, datas[i * 4]);
        crc = pec_crc_push(crc, datas[i * 4 + 1]);
        printf("%d[%04d]: 0x%02X%02X  0x%04X 0x%04X\n", i, i * 4, datas[i * 4 + 2], datas[i * 4 + 3], crc, crc2);
    }
    printf("\n");
    uint8_t datas2[] = {0xff, 0x0f, 0x00, 0x60, 0x00, 0x00, 0x04, 0x02};
    printf("%x\n", pec_crc(datas2, 6));
    return 0;
}
#endif
